/*package com.level.restful.util.httpLogUtil;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.level.restful.entity.TExceptionLog;
import com.level.restful.entity.TRequestLog;
import com.level.restful.service.ExceptionLogRepository;
import com.level.restful.service.RequestLogRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Map;

*//**
 * @author
 *  声明这是一个切面类
 *  此类交由Spring容器管理
 *  参考地址https://www.jianshu.com/p/d8a654993719
 *//*
@Slf4j
@Aspect
@Component
public class RequestLogAspect {
    *//**
     * 使用ThreadLocal避免多线程调用线程安全问题
     *//*
    private  static ThreadLocal<TRequestLog>  localRequestLog = new ThreadLocal<TRequestLog>();

    private ThreadLocal<TExceptionLog> exceptionLog = new ThreadLocal<TExceptionLog>();


    private long startTime;

    private long returnTime;

    @Autowired
    private RequestLogRepository requestLogRepository;


    @Autowired
    private ExceptionLogRepository exceptionLogRepository;


    @Autowired
    private HttpServletRequest request;

    private static ThreadLocal<HttpServletRequest> local = new ThreadLocal<HttpServletRequest>();

    *//**
     * 定义请求日志切入点：
     * @PointCut 定义请求日志切入点，其切入点表达式有多种匹配方式，详细请自行参阅资料，此处切入点为所有声明@Operation注解的方法
     *
     * execution(* com.level.home.controller.Html5Controller.updateEmr_BASY_info(..))
     * serviceStatistics(operation)
     * @param
     *
     * @Pointcut("execution(* com.level.restful.web.*(..))")
     *//*
    @Pointcut(value="execution(* com.level.restful.web.*.*(..))")
    public void serviceStatistics(){

    }

    *//**
     * 前置通知
     * 前置通知在执行目标方法之前执行
        在前置通知中设置请求日志信息，如开始时间，请求参数，注解内容等
     *
     *//*
    @Before(value="serviceStatistics()")
    public void doBefor(JoinPoint joinPoint) throws RequestException, NotFindException, ClassException{
        try{
        // 获取切入点参数
            Map<String,Object> joinPointInfo = RequestUtil.getJoinPointInfoMap(joinPoint);
            TRequestLog requestLog = localRequestLog.get();
            // 设置请求信息
            startTime = System.currentTimeMillis();
            requestLog.setStartTime(DateUtil.parse(startTime));
            requestLog.setIp(RequestUtil.getRequestIp(request));
            requestLog.setClassPath(joinPointInfo.get("classPath").toString());
            requestLog.setMethodName(joinPointInfo.get("methodName").toString());
            requestLog.setWay(request.getMethod());
            requestLog.setParam(getReqParameter(request));
            requestLog.setType(RequestUtil.getRequestType(request));
            requestLog.setSessionId(request.getSession().getId());
            requestLog.setUrl(request.getRequestURL().toString());

            TExceptionLog tExceptionLog  = new TExceptionLog();
            exceptionLog.set(tExceptionLog);
            tExceptionLog.setClassPath(joinPointInfo.get("classPath").toString());
            tExceptionLog.setMethodName(joinPointInfo.get("methodName").toString());
            tExceptionLog.setParam(getReqParameter(request));

        }catch (Exception e){
            log.error("日志切面方法 doBefor 出错：",e);
            throw e;
        }

    }

    *//**
     * 返回通知，在目标方法正常结束之后执行
     在返回通知中补充请求日志信息，如返回时间，方法耗时，返回值，并且保存日志信息
     * @param returnValue
     *//*
    @AfterReturning(value="serviceStatistics()",returning = "returnValue")
    public void doAfeterReturning(Object returnValue) {
            // 完善请求信息
        try{


            returnTime = System.currentTimeMillis();
            localRequestLog.get().setReturnTime(DateUtil.parse(returnTime));
            localRequestLog.get().setFinishTime(DateUtil.timeDifferLong(startTime,returnTime));
            localRequestLog.get().setReturnData(JSON.toJSONString(returnValue, SerializerFeature.DisableCircularReferenceDetect,
                    SerializerFeature.WriteMapNullValue));
            // 保存请求日志信息
            requestLogRepository.save(localRequestLog.get());
            localRequestLog.remove();
        }catch (Exception e){
            log.error("切面日志 doAfeterReturning 方法 出错" ,e);
        }
    }

    *//**
     * 异常通知，在目标方法非正常结束，发生异常或者抛出异常时执行
     在异常通知中设置异常信息，并将其保存
     * @param
     * @param e
     *//*
    @AfterThrowing(value="serviceStatistics()",throwing = "e")
    public void doAfterThrowing(Throwable e){
            // 设置异常信息
        try{


            long happenTime = System.currentTimeMillis();
            exceptionLog.get().setHappenTime(DateUtil.parse(happenTime));
            exceptionLog.get().setExceptionJson(JSON.toJSONString(e, SerializerFeature.DisableCircularReferenceDetect,
                        SerializerFeature.WriteMapNullValue));
            exceptionLog.get().setExceptionMessage(e.getMessage());

            // 保存异常信息
            exceptionLogRepository.save(exceptionLog.get());
            exceptionLog.remove();
        }catch (Exception error){
            log.error("切面日志 doAfterThrowing 方法 出错" ,error);
        }
    }

    *//**
     * 获取请求入参
     * @param request
     * @return
     *//*
    public String getReqParameter(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        Enumeration<String> enumeration = request.getParameterNames();
        JSONArray jsonArray = new JSONArray();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getParameter(key);
            JSONObject json = new JSONObject();
            json.put(key, value);
            jsonArray.add(json);
        }
        return jsonArray.toString();
    }


    *//**
     * 定义一个切入点
     *//*
    @Pointcut(value="execution(* com.level.restful.web.*.*(..))")
    private void cutOpenId(){

    }

    *//**
     * 环绕通知（此处采用环绕通知的原因 ：1抛出异常后程序不会继续向下执行  2可以改变返回类型）
     * @param point
     * @return
     * @throws Throwable
     *//*
    @Around("cutOpenId()")
    public Object doOpenId(ProceedingJoinPoint point) throws Throwable{
        TRequestLog requestLog = new TRequestLog();
        localRequestLog.set(requestLog);

        MethodSignature ms = (MethodSignature) point.getSignature();
        String openId = request.getParameter("openId");

        if(StringUtils.isBlank(openId)){
            throw new OpenIdAuthException("token不能为空");
        }else{
            if(openId.length() != 28){
                throw new OpenIdAuthException("token不正确");
            }
            return point.proceed();
        }
        return point.proceed();
    }

    *//**
     * 将request绑定到当前线程的方法
     * @param requestLog
     *//*
    private void setLocal(TRequestLog requestLog){
        localRequestLog.set(requestLog);
    }

    *//**
     *  从当前线程获取request的方法
     * @return
     *//*
    public static TRequestLog getRequest() {
        return localRequestLog.get();
    }

    *//**
     * 从当前线程移除request的方法
     *//*
    public static void removeRequest() {
        localRequestLog.remove();
    }
}
*/